package com.heima.app.gateway.filter;

import com.heima.app.gateway.util.AppJwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component//将AuthorizeFilter类声明为Spring组件，使得Spring容器可以自动发现并管理它
@Slf4j// Lombok注解，用于简化日志记录代码的编写
//Spring Cloud Gateway中的全局过滤器，用于实现用户授权验证的功能
//实现Ordered和GlobalFilter接口，用于定义过滤器的优先级和全局过滤器行为
public class AuthorizeFilter implements Ordered, GlobalFilter {

	@Override
	//filter方法是GlobalFilter接口的核心方法，用于在请求进入路由之前对请求进行处理
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		//1.获取request和response对象
		ServerHttpRequest request = exchange.getRequest();
		ServerHttpResponse response = exchange.getResponse();

		//2.判断是否是登录,判断请求路径是否包含"/login"，即是否是登录请求
		//对于登录请求的话，直接放行；对于其他请求，需要判断token是否存在并且token是否有效
		if(request.getURI().getPath().contains("/login")){
			//放行
			return chain.filter(exchange);
		}


		//3.获取当前token
		String token = request.getHeaders().getFirst("token");

		//4.判断token是否存在
		if(StringUtils.isBlank(token)){
			//token不存在，直接提示未认证
			response.setStatusCode(HttpStatus.UNAUTHORIZED);
			return response.setComplete();
		}

		//5.如果token存在，就判断token是否有效
		try {
			//使用AppJwtUtil.getClaimsBody方法解析token，获取其中的有效负载
			Claims claimsBody = AppJwtUtil.getClaimsBody(token);
			//使用AppJwtUtil.verifyToken方法验证token的有效性，返回的结果可能表示不同的验证状态
			int result = AppJwtUtil.verifyToken(claimsBody);
			//如果token验证失败（即result为1或2），则设置HTTP状态码为401（未授权），并返回已完成的响应
			if(result == 1 || result  == 2){
				response.setStatusCode(HttpStatus.UNAUTHORIZED);
				return response.setComplete();
			}

			//获得token解析后中的用户信息（我们根据id生成jwt，这里进行相反的操作）
			Object userId = claimsBody.get("id");
			//如果token有效，则从claims中获取用户ID，并将用户ID添加到请求头中，以便后续服务可以使用该信息进行处理
			ServerHttpRequest serverHttpRequest = request.mutate().headers(httpHeaders -> {
				httpHeaders.add("userId", userId + "");
			}).build();
			//使用request.mutate()方法修改请求头，并将新的请求头设置回ServerWebExchange中
			exchange.mutate().request(serverHttpRequest).build();
		}catch (Exception e){
			e.printStackTrace();
			response.setStatusCode(HttpStatus.UNAUTHORIZED);
			return response.setComplete();
		}

		//6.放行
		return chain.filter(exchange);
	}

	/**
	 * 优先级设置  值越小  优先级越高
	 * 当有多个过滤器的时候，就按照过滤器的优先级的顺序执行
	 * @return
	 */
	@Override
	public int getOrder() {
		//0表示AuthorizeFilter在所有过滤器中优先级最高
		//这表示所有的请求都会先在这个过滤器被处理，处理结束后其他过滤器才能接着排队处理
		return 0;
	}
}